package threadingexercise;


//模拟实现阻塞队列，不是泛型的版本
// 1. 实现一个正常的队列
// 2. 加上线程安全
// 3. 加上阻塞功能 wait notify
class MyBlockingQueue {
    private int[] items = new int[100];

    //多次读操作
    volatile private int head = 0;   //队首
    volatile private int tail = 0;   //队尾
    volatile private int size = 0;   //存放的元素个数

    //入队列  最简单的就是直接在方法上加锁 (有多次修改数据的操作)
    synchronized public void put(int value) throws InterruptedException { //InterruptedException , InterruptedException {
         /*if(size == 0) {
            //队列为空
            //return null;
            this.wait();
        }*/

        //改成 while 防止被其它方法给提前唤醒 wait 比如 interrut方法
        // 所以换成 while 加一步确认的
        while(size == 0) {
            //队列为空
            //return null;
            this.wait();
        }
        items[tail] = value;
        tail++;
        //加完之后到最后了
        if(tail == items.length) {
            tail = 0;
        }
        // tail = tail % items.length; 这种写法也是可以的，但是不便于理解
        size++;
        this.notify();
    }


    //出队列
    synchronized public Integer take() throws InterruptedException{
        /*if(size == 0) {
            //队列为空
            //return null;
            this.wait();
        }*/

        //改成 while 防止被其它方法给提前唤醒 wait 比如 interrut方法
        // 所以换成 while 加一步确认的
        while(size == 0) {
            //队列为空
            //return null;
            this.wait();
        }
        int value = items[head];
        head++;
        if(head == items.length) {
            head = 0;
        }
        size--;

        //出队列的时候进行唤醒 执行到wait的时候才会执行notify
        this.notify();
        return value;
    }
}

//不写 泛型 的版本，同时基于数组实现
public class ThreadDemo21Simulation {
    public static void main(String[] args) {
        MyBlockingQueue queue = new MyBlockingQueue();
    }
}
